#include "../easyunit/test.h"
#include "../source/factory/Factory.h"

using namespace easyunit;

DECLARE(Graph)
	Factory* f;
	Graph *g1, *g2, *g3, *g4, *g5, *g6, *g7, *g8;
	
END_DECLARE

SETUP(Graph)
{
	f = Factory::getInstance();
	g1 = f->createGraph(10, 1);
	g2 = f->createGraph(15, 1);
	g3 = f->createGraph(0, 0);
	g4 = f->createGraph(0, 1);
	g5 = f->createGraph(1, 1);
	g6 = f->createGraph(10, 0.5);
	g7 = f->createGraph(2, 0);
	g8 = f->createGraph(3, 0);
}

TEARDOWN(Graph)
{
}

TESTF(Graph, addNode)
{
	Node * n1 = new Node(1);

	g1->addNode(new Node(11));
	ASSERT_TRUE(g1->numberOfNode() == 11);
	g1->addNode(new Node(11)); //Impossible
	ASSERT_TRUE(g1->numberOfNode() == 11);

	g2->addNode(n1); //Forbidden to add node with ID = 1, already exists
	ASSERT_TRUE(g2->numberOfNode() == 15);

	g3->addNode(n1);
	ASSERT_TRUE(g3->numberOfNode() == 1);

    	g4->addNode(n1);
   	ASSERT_TRUE(g4->numberOfNode() == 1);
}

TESTF(Graph, numberOfNode)
{
    ASSERT_TRUE(g1->numberOfNode() == 10);
    g1->addNode(new Node(11));
    ASSERT_TRUE(g1->numberOfNode() == 11);

    ASSERT_TRUE(g2->numberOfNode() == 15);
    g2->addNode(new Node(2));
    ASSERT_TRUE(g2->numberOfNode() == 15);

    ASSERT_TRUE(g3->numberOfNode() == 0);

    ASSERT_TRUE(g4->numberOfNode() == 0);

    ASSERT_TRUE(g6->numberOfNode() == 10);

    ASSERT_TRUE(g7->numberOfNode() == 2);
}

TESTF(Graph, numberOfEdge)
{
    ASSERT_TRUE(g1->numberOfEdge() == 45);
    ASSERT_TRUE(g2->numberOfEdge() == 105);
    ASSERT_TRUE(g3->numberOfEdge() == 0);
    ASSERT_TRUE(g4->numberOfEdge() == 0);
    ASSERT_TRUE(g5->numberOfEdge() == 0);
    ASSERT_TRUE(g5->numberOfEdge() == 0);
}

TESTF(Graph, createEdge)
{
    g1->createEdge(g1->nodeAt(0), g1->nodeAt(1));
    ASSERT_TRUE(g1->numberOfEdge() == 45);
    g1->createEdge(g1->nodeAt(1), g1->nodeAt(0));
    ASSERT_TRUE(g1->numberOfEdge() == 45);

    g2->createEdge(g2->nodeAt(0), g2->nodeAt(1));
    ASSERT_TRUE(g2->numberOfEdge() == 105);

    int nbEdgeG6 = g6->numberOfEdge();
    g6->createEdge(g6->nodeAt(0), g6->nodeAt(1));
    ASSERT_TRUE((g6->numberOfEdge() == nbEdgeG6) || (g6->numberOfEdge() == nbEdgeG6 + 1));
    ASSERT_TRUE(g6->numberOfNode() == 10);

    g7->createEdge(g7->nodeAt(0), g7->nodeAt(1));
    ASSERT_TRUE(g7->numberOfEdge() == 1);
    ASSERT_TRUE(g7->numberOfNode() == 2);
}

TESTF(Graph, hasLeaf)
{
    ASSERT_TRUE(g1->hasLeaf() == false);
    ASSERT_TRUE(g2->hasLeaf() == false);
    ASSERT_TRUE(g3->hasLeaf() == false);
    ASSERT_TRUE(g4->hasLeaf() == false);
    ASSERT_TRUE(g5->hasLeaf() == false);

    ASSERT_TRUE(g7->hasLeaf() == false);
    g7->createEdge(g7->nodeAt(0), g7->nodeAt(1));
    ASSERT_TRUE(g7->hasLeaf() == true);

    ASSERT_TRUE(g8->hasLeaf() == false);
    g8->createEdge(g8->nodeAt(0), g8->nodeAt(1));
    ASSERT_TRUE(g8->hasLeaf() == true);
    g8->createEdge(g8->nodeAt(0), g8->nodeAt(2));
    g8->createEdge(g8->nodeAt(1), g8->nodeAt(2));
    ASSERT_TRUE(g8->hasLeaf() == false);
}

TESTF(Graph, eraseEdgesOfNode)
{
	g1->eraseEdgesOfNode(g1->nodeAt(0));
	ASSERT_TRUE(g1->numberOfNode() == 10);
	ASSERT_TRUE(g1->numberOfEdge() == 36);
	g1->eraseEdgesOfNode(g1->nodeAt(1));
	ASSERT_TRUE(g1->numberOfEdge() == 28);

	g2->eraseEdgesOfNode(g2->nodeAt(0));
	ASSERT_TRUE(g2->numberOfNode() == 15);
	ASSERT_TRUE(g2->numberOfEdge() == 91);

	g5->eraseEdgesOfNode(g5->nodeAt(0));
	ASSERT_TRUE(g5->numberOfNode() == 1);
	ASSERT_TRUE(g5->numberOfEdge() == 0);

	int nbEdgeG6 = g6->numberOfEdge();
	int nbEdgeG6Node0 = g6->nodeAt(0)->outDeg();
	g6->eraseEdgesOfNode(g6->nodeAt(0));
	ASSERT_TRUE(g6->numberOfNode() == 10);
	ASSERT_TRUE(g6->numberOfEdge() == (nbEdgeG6 - nbEdgeG6Node0));
}

TESTF(Graph, getFatherOfLeaf)
{
	int actualID;
	g7->createEdge(g7->nodeAt(0), g7->nodeAt(1));
	actualID = g7->getFatherOfLeaf()->getID();
	ASSERT_TRUE( (actualID == 1) || (actualID == 2));
	g7->addNode(new Node(3));
	g7->addNode(new Node(4));
	g7->createEdge(g7->nodeAt(1), g7->nodeAt(2));
	actualID = g7->getFatherOfLeaf()->getID();
	ASSERT_TRUE(actualID == 2);
	g7->createEdge(g7->nodeAt(2), g7->nodeAt(3));
	actualID = g7->getFatherOfLeaf()->getID();
	ASSERT_TRUE( (actualID == 2) || (actualID == 3));
	g7->createEdge(g7->nodeAt(0), g7->nodeAt(2));
	actualID = g7->getFatherOfLeaf()->getID();
	ASSERT_TRUE(actualID == 3);
}
